<?php

namespace App\Http\Controllers\Web\Buyer;

use App\ConstDir\ErrorConst;
use App\Events\OrderAffirmEvent;
use App\Events\OrderCancelEvent;
use App\Http\Controllers\Web\BaseController;
use App\Repository\Models\Invoices;
use App\Repository\Models\OrderProducts;
use App\Repository\Models\Orders;
use App\Repository\Models\OrdersCrontab;
use App\Repository\Repositories\Interfaces\AddressRepository;
use App\Repository\Repositories\Interfaces\CartsRepository;
use App\Repository\Repositories\Interfaces\CompanyRepository;
use App\Repository\Repositories\Interfaces\InvoicesRepository;
use App\Repository\Repositories\Interfaces\OrderExpressRepository;
use App\Repository\Repositories\Interfaces\OrderProductCommentRepository;
use App\Repository\Repositories\Interfaces\OrderProductsRepository;
use App\Repository\Repositories\Interfaces\OrdersCrontabRepository;
use App\Repository\Repositories\Interfaces\OrdersRepository;
use App\Repository\Repositories\Interfaces\ProductSkusRepository;
use App\Repository\Repositories\Interfaces\ProductsRepository;
use App\Repository\Repositories\Interfaces\ShopRepository;
use App\Repository\Repositories\Interfaces\UserInvoiceRepository;
use App\Services\Api\KuaiDi100;
use App\Services\Pay\CzbankService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

/**
 * 订单管理控制器
 *
 * @package App\Http\Controllers\Backend
 */
class OrdersController extends BaseController
{
    /**
     * @var OrdersRepository
     */
    protected $orders_repo;

    protected $user_id;
    protected $api_url = [
        'order_query' => ['post', 'orderQuery'],
    ];

    public function __construct(OrdersRepository $orders_repo)
    {
        parent::__construct();
        $this->orders_repo = $orders_repo;
        $this->user_id = array_get($this->user, 'id');

        //用户只能操作自身所属数据,******每次请求只生效一次*******
        $this->orders_repo->scopeQuery(function ($query) {
            return $query->where('user_id', $this->user_id);//->where('order_type','!=',6);
        });
    }

    /**
     * 订单列表
     * @return \Illuminate\Support\Collection
     */
    public function index()
    {
        $orders = $this->orders_repo->paginate($this->perPage);


        return $this->success(ErrorConst::SUCCESS_CODE_MSG, $orders, true);
    }

    /**
     * 支付订单列表
     * @param Request $request
     * @return \Illuminate\Support\Collection
     */
    public function payList(Request $request)
    {
        $data = $request->all(['order_codes']);
        $order_codes = explode(',', $data['order_codes']);
        $orders = $this->orders_repo->findWhereIn('order_code', $order_codes);
        return $this->success(ErrorConst::SUCCESS_CODE_MSG, $orders['data']);
    }

    /**
     * 订单详情
     * @param $id
     * @return \Illuminate\Support\Collection
     */
    public function show($id)
    {
        $order = $this->orders_repo->find($id);
        return $this->success(ErrorConst::SUCCESS_CODE_MSG, $order['data']);
    }

    /**
     * 订单创建
     * @param Request $request
     * @param ProductsRepository $products_repo
     * @param ProductSkusRepository $product_skus_repo
     * @param OrdersRepository $orders_repo
     * @param OrderProductsRepository $order_products_repo
     * @param CompanyRepository $shop_repo
     * @param AddressRepository $address_repo
     * @param UserInvoiceRepository $user_invoice_repo
     * @param InvoicesRepository $invoices_repo
     * @param CartsRepository $carts_repo
     * @return \Illuminate\Support\Collection
     */
    public function store(Request $request, ProductsRepository $products_repo, ProductSkusRepository $product_skus_repo, OrdersRepository $orders_repo,
                          OrderProductsRepository $order_products_repo, ShopRepository $shop_repo, AddressRepository $address_repo,
                          UserInvoiceRepository $user_invoice_repo, InvoicesRepository $invoices_repo, CartsRepository $carts_repo,
                          OrdersCrontabRepository $orders_crontab_repo)
    {
        $this->validate($request, [
            'address_id' => 'required|integer',
            'invoices' => 'array',  //店铺ID=>发票ID
            'remark' => 'array',
            'sku_num' => 'required|array', //SKU-ID=>购买数量，例如：[223=>2,322=>1]
            'ip' => 'string'
        ]);
        $data = $request->all(['address_id', 'invoices', 'remark', 'sku_num']);

        //一次获取所有产品
        $sku_ids = array_keys($data['sku_num']);
        $skus = $product_skus_repo->with(['product' => function ($sql) {
            $sql->select(['id', 'shop_id', 'name', 'model', 'brand_id', 'cover_image', 'status', 'is_for_sale']);
        }])->findWhereIn('id', $sku_ids, ['id', 'product_id', 'sale_price', 'attributes', 'freight']);

        //根据店铺分组，不信任前端传过来的店铺商品分组，此处重新分组
        $shop_ids = [];
        $shop_skus = [];
        foreach ($skus['data'] as $sku) {
            //如果存在下架或审核不通过商品，则返回错误
            if(!$sku['product']['available']){
                return $this->error(ErrorConst::PRODUCT_SOLD_OUT_MSG, ErrorConst::PRODUCT_SOLD_OUT);
            }
            $sku['quantity'] = $data['sku_num'][$sku['id']];
            $shop_ids[] = $sku['product']['shop_id'];
            $shop_skus[$sku['product']['shop_id']][] = $sku;
        }
//        $shops = $shop_repo->with(['shop'])->findWhereIn('id', $shop_ids, ['id', 'company_name']);
        $shops = $shop_repo->findWhereIn('sp_id', $shop_ids, ['sp_id', 'sp_name']);
        array_walk($shops['data'], function (&$value, $key) use ($shop_skus) {
            $value['skus'] = $shop_skus[$value['sp_id']];
        });

        //发票信息公共部分
        if($data['invoices']){
            $invoices = $user_invoice_repo->findWhereIn('id', array_unique($data['invoices']), [
                'id', 'invoice_message', 'invoice_type', 'invoice_title', 'tax_code', 'invoice_address',
                'invoice_tel', 'invoice_bank', 'invoice_account', 'post_address', 'post_contacts', 'post_tel'
            ]);
            //为店铺分配发票
            foreach($invoices['data'] as $invoice){
                array_walk($data['invoices'], function(&$value, $key) use ($invoice){
                    $value = $value == $invoice['id'] ? $invoice : null;
                });
            }
        }else{
            $invoices = [];
        }

        //寄送地址
        $address = $address_repo->find($data['address_id'], ['receiver', 'phone', 'address']);

        //生成的订单
        $order_codes = [];

        \DB::beginTransaction();
        try {
            foreach ($shops['data'] as $shop) {
                $shop_remark = array_get($data['remark'], $shop['sp_id']);
                $shop_data = $this->calculateSingleShop($shop, $shop_remark);
                //生成订单
                $order_data = $shop_data['order'] + $address['data'];
                $order = $orders_repo->create($order_data);
                $order_codes[] = $order['data']['order_code'];

                //生成订单商品
                $product = $order_products_repo->batchCreate($shop_data['order_products'], $order['data']['order_code']);

                //生成订单自动取消记录
                $order_time = array_get($shop, 'shop.order_time') ? : 3600*24;
                $orders_crontab_cancel_data = [
                    'expired_at' => date('Y-m-d H:i:s', time() + $order_time),
                    'order_id' => $order['data']['id'],
                    'type' => OrdersCrontab::TYPE_CANCEL
                ];
                $orders_crontab_repo->create($orders_crontab_cancel_data);

                //生成订单自动确认记录
                $receipt_time = array_get($shop, 'shop.receipt_time') ? : 3600*24*14;
                $orders_crontab_affirm_data = [
                    'expired_at' => date('Y-m-d H:i:s', time() + $receipt_time),
                    'order_id' => $order['data']['id'],
                    'type' => OrdersCrontab::TYPE_AFFIRM
                ];
                $orders_crontab_repo->create($orders_crontab_affirm_data);

                //发票创建
                if($data['invoices'][$shop['sp_id']]){
                    $data['invoices'][$shop['sp_id']]['invoice_price'] = $shop_data['order']['order_money'];
                    $data['invoices'][$shop['sp_id']]['user_id'] = $this->user_id;
                    $data['invoices'][$shop['sp_id']]['order_code'] = $order['data']['order_code'];
                    $invoices_repo->create($data['invoices'][$shop['sp_id']]);
                }
            }

            //减库存
            foreach ($data['sku_num'] as $sku_id => $num) {
                $product_skus_repo->decrementStock($sku_id, $num);
            }

            //删除购物车信息
            $carts_repo->batchDeleteBySku($sku_ids, $this->user_id);

            $ret = true;
            \DB::commit();
        } catch (\Exception $e) {
            throw  new \Exception($e);
            \DB::rollback(); //事务回滚;
            $ret = false;
        }

        if($ret){
            return $this->success(ErrorConst::SUCCESS_CODE_MSG, ['order_codes' => $order_codes]);
        }else{
            return $this->error(ErrorConst::FAILED_CODE_MSG, ErrorConst::FAILED_CODE);
        }
    }

    /**
     * 订单更新
     * @param Request $request
     * @param $id
     * @return \Illuminate\Support\Collection
     */
    public function update(Request $request, $id)
    {
        $this->validate($request, [
            'order_status' => 'required|in:' . Orders::ORDER_STATUS_AFFIRM . ',' . Orders::ORDER_STATUS_CANCEL,
        ]);
        $data = $request->all(['order_status']);

        if($data['order_status'] == Orders::ORDER_STATUS_AFFIRM){
            
            //
            $order = $this->orders_repo->find($id);
            $trade_no = isset($order['data']['trade_no']) ? $order['data']['trade_no'] : "";
            $data = [
                'tradeNo' => $trade_no,
            ];
            
            $query_ret = http_czbank($this->api_url['order_query'])->send($data);
            if(isset($query_ret['data']['tradeStt']) && $query_ret['data']['tradeStt'] !=4 ){
                return $this->error("为了保证交易的真实性和安全性，请你在发货48小时以后确认收货。");
            }
            //
            //订单确认收货
            $ret = event(new OrderAffirmEvent(['order_id' => $id]));
        }elseif($data['order_status'] == Orders::ORDER_STATUS_CANCEL){
            //订单取消
            $ret = event(new OrderCancelEvent(['order_id' => $id]));
        }else{
            //
        }

        return $this->noDataReturn($ret);
    }

    /**
     * 根据店铺计算
     * @param $shop
     * @return array
     */
    private function calculateSingleShop($shop, $shop_remark)
    {
        $order = [
            'user_id' => $this->user_id,
            'shop_id' => $shop['sp_id'],
            'initial_product_money' => 0.00,
            'initial_freight_money' => 0.00,
        ];
        $order_products = [];

        foreach ($shop['skus'] as $sku) {
            $order['initial_product_money'] += $sku['sale_price'] * $sku['quantity'];
            $order['initial_freight_money'] += $sku['freight'] * $sku['quantity'];
            $order_products[] = [
                'shop_id' => $shop['sp_id'],
                'shop_name' => $shop['sp_name'],
                'product_price' => $sku['sale_price'],
                'quantity' => $sku['quantity'],
                'product_money' => $sku['sale_price'] * $sku['quantity'],
                'attributes' => $sku['attributes'],
                'sku_id' => $sku['id'],
                'product_id' => $sku['product']['id'],
                'product_name' => $sku['product']['name'],
                'model' => $sku['product']['model'],
                'brand_name' => $sku['product']['brand_id'],
                'product_img_url' => $sku['product']['cover_image'],
                'user_id' => $this->user_id,
            ];
        }

        //无优惠卷时，创建订单时，初始价格与最终价格一致
        $order['order_money'] = $order['initial_product_money'] + $order['initial_freight_money'];
        $order['product_money'] = $order['initial_product_money'];
        $order['freight'] = $order['initial_freight_money'];
        $order['remark'] = $shop_remark;

        return compact('order', 'order_products');
    }

    /**
     * 计算用户的各状态订单数量
     * @param
     * @return array
     */
    public function countOrders(){
        $orders = [];
        // 待付款
        $orders['NoPay'] = Orders::query()->where(['order_status'=> '1','user_id'=>$this->user_id])->count();
        // 待发货
        $orders['Payed'] = Orders::query()->where(['order_status'=>'2','user_id'=>$this->user_id])->count();
        // 待收货
        $orders['Delivery'] = Orders::query()->where(['order_status'=> '3','user_id'=>$this->user_id])->count();
        // 待确认
        $orders['Comment']  = Orders::query()->where(['order_status'=> '4','buyer_comment_status'=> '0','user_id'=>$this->user_id])->count();

        return $this->success(ErrorConst::SUCCESS_CODE_MSG, $orders);
    }
    /**
     * showOrderExpress
     * */
    public function showOrderExpress(KuaiDi100 $kuaidi100, OrderExpressRepository $order_express_repo, $order_id)
    {
        $order = $this->orders_repo->with(['orderExpress'])->find($order_id);

        if ($order_express = $order['data']['order_express']) {
            //如果已签收，则数据从数据库中取
            if ($order_express['state'] != 3) {
                if ($order_express['company_code'] && $order_express['waybill_number']) {
                    $ret = $kuaidi100->getLogisticsInfo(['company_code' => $order_express['company_code'], 'waybill_number' => $order_express['waybill_number']]);
                }

                //如果已签收，则以后数据不再重新查询
                if (isset($ret['status']) && $ret['status'] == 200) {
                    $order_express['state'] = $ret['state'];
                    $order_express['result'] = json_encode($ret['data']);

                    $order_express = $order_express_repo->update($order_express, $order_express['id']);
                }
            }

            return $this->success(ErrorConst::SUCCESS_CODE_MSG, $order_express);
        } else {
            return $this->error(ErrorConst::ERROR_CODE_MSG, ErrorConst::ERROR_CODE);
        }
    }


    /**
    * 订单列表
    * @return \Illuminate\Support\Collection
    */
    public function buyer_index()
    {
        $orders=$this->orders_repo->scopeQuery(function ($query) {
            return $query->where('user_id', $this->user_id)->whereIn('order_type',[1,6])->limit(1);//->where('order_type','!=',6);
        })->all();

      return $this->success(ErrorConst::SUCCESS_CODE_MSG, $orders['data'], true);
    }
}
